﻿/*
 * Unknown.h
 *
 */

#ifndef __GDK_UNKNOWN_H__
#define __GDK_UNKNOWN_H__


#include <gdk/core/Types.h>
#include <gdk/core/Utility.h>
#include <gdk/core/atomics.h>
#include <gdk/core/String.h>
#include <gdk/core/Memory.h>
#include <gdk/core/Exception.h>
#include <gdk/core/cpptypeid.h>
#include <gdk/core/CallStack.h>

#include <map>
#include <vector>


namespace gdk
{




////////////////////////////////////////
#define DECLARE_CLASS_SERIALIZE(Class) \
	public:\
		template<typename Tyis_> friend Tyis_& operator >>(Tyis_ &, Class &) __THROW1;\
		template<typename Tyos_> friend Tyos_& operator <<(Tyos_ &, Class const &) __THROW1;\
	public:\
		gdk::Unknown::Handle_T<Class> clone(void) const\
		{\
			return gdk::Unknown::clone()->dynamicCast<Class>();\
		}\
		virtual void importFrom(gdk::InputStream &is) __THROW1\
		{\
			is >> *this;\
		}\
		virtual void exportTo(gdk::OutputStream &os) const __THROW1\
		{\
			os << *this;\
		}\
	private:


#define DECLARE_CLASS_HANDLE(Class) \
	public:\
		typedef gdk::Unknown::Handle_T<Class>		Handle;\
		typedef gdk::Unknown::Handle_T<Class const>	ConstHandle;\
	private:\
		friend class gdk::Unknown::Handle_T<Class>;\
		friend class gdk::Unknown::Handle_T<Class const>;\
	public:\
		virtual const gdk::Char* getClassTimestamp(void) const { return __TEXT__(__TIMESTAMP__); }\
	public:\
		template<typename Tyclass_>\
		__INLINE__ Tyclass_* staticCast(void)\
		{\
			return static_cast<Tyclass_*>(this);\
		}\
		template<typename Tyclass_>\
		__INLINE__ Tyclass_* dynamicCast(void)\
		{\
			return dynamic_cast<Tyclass_*>(this);\
		}\
		template<typename Tyclass_>\
		__INLINE__ Tyclass_ const* staticCast(void) const\
		{\
			return static_cast<Tyclass_ const*>(this);\
		}\
		template<typename Tyclass_>\
		__INLINE__ Tyclass_ const* dynamicCast(void) const\
		{\
			return dynamic_cast<Tyclass_ const*>(this);\
		}

#define DECLARE_CLASS_INSTANCE(Class) \
	public:\
		static gdk::Unknown::Handle_T<Class> createInstance(void)\
		{\
			return GDK_NEW Class();\
		}\
	private:


#define DECLARE_CLASS_INSTANCE1(Class,A) \
	public:\
		static gdk::Unknown::Handle_T<Class> createInstance(A a)\
		{\
			return GDK_NEW Class(a);\
		}\
	private:


#define DECLARE_CLASS_INSTANCE2(Class,A,B) \
	public:\
		static gdk::Unknown::Handle_T<Class> createInstance(A a,B b)\
		{\
			return GDK_NEW Class(a,b);\
		}\
	private:


#define DECLARE_CLASS_INSTANCE3(Class, A, B, C) \
	public:\
		static gdk::Unknown::Handle_T<Class> createInstance(A a, B b, C c)\
		{\
			return GDK_NEW Class(a, b, c);\
		}\
	private:


#define DECLARE_CLASS_INSTANCE4(Class, A, B, C, D) \
	public:\
		static gdk::Unknown::Handle_T<Class> createInstance(A a, B b, C c, D d)\
		{\
			return GDK_NEW Class(a, b, c, d);\
		}\
	private:


#define DECLARE_CLASS_INSTANCE5(Class, A, B, C, D, E) \
	public:\
		static gdk::Unknown::Handle_T<Class> createInstance(A a, B b, C c, D d, E e)\
		{\
			return GDK_NEW Class(a, b, c, d, e);\
		}\
	private:


#define DECLARE_CLASS_INSTANCE6(Class, A, B, C, D, E, F) \
	public:\
		static gdk::Unknown::Handle_T<Class> createInstance(A a, B b, C c, D d, E e, F f)\
		{\
			return GDK_NEW Class(a, b, c, d, e, f);\
		}\
	private:


#define DECLARE_CLASS_INSTANCE7(Class, A, B, C, D, E, F, G) \
	public:\
		static gdk::Unknown::Handle_T<Class> createInstance(A a, B b, C c, D d, E e, F f, G g)\
		{\
			return GDK_NEW Class(a, b, c, d, e, f, g);\
		}\
	private:


#define DECLARE_CLASS_INSTANCE8(Class, A, B, C, D, E, F, G, H) \
	public:\
		static gdk::Unknown::Handle_T<Class> createInstance(A a, B b, C c, D d, E e, F f, G g, H h)\
		{\
			return GDK_NEW Class(a, b, c, d, e, f, g, h);\
		}\
	private:


#define DECLARE_CLASS_INSTANCE9(Class, A, B, C, D, E, F, G, H, I) \
	public:\
		static gdk::Unknown::Handle_T<Class> createInstance(A a, B b, C c, D d, E e, F f, G g, H h, I i)\
		{\
			return GDK_NEW Class(a, b, c, d, e, f, g, h, i);\
		}\
	private:


#define DECLARE_CLASS_INSTANCE10(Class, A, B, C, D, E, F, G, H, I, J) \
	public:\
		static gdk::Unknown::Handle_T<Class> createInstance(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j)\
		{\
			return GDK_NEW Class(a, b, c, d, e, f, g, h, i, j);\
		}\
	private:




#define DECLARE_RT_CREATOR(className) \
	private:\
		friend class gdk::Unknown::RtFactory;\
	public:\
		static const gdk::String	g_className_;\
		static const gdk::ClassId	g_classId_;\
		static const bool 			g_setUpCreator_;\
	private:\
		static gdk::Unknown::Handle_T<gdk::Unknown> rtCreateInstance_(void);\
	public:\
		__INLINE__ static const gdk::String& getClassName_(void) { return g_className_; }\
		__INLINE__ static gdk::ClassId getClassId_(void) { return g_classId_; }\
	public:\
		virtual const gdk::String& getClassName(void) const { return g_className_; }\
		virtual gdk::ClassId getClassId(void) const { return g_classId_; }\
		virtual gdk::Unknown::Handle_T<gdk::Unknown> rtCreateInstance(void) const;\
	private:


#define IMPLEMENT_RT_CREATOR(className) \
	gdk::Unknown::Handle_T<gdk::Unknown> className::rtCreateInstance_(void)\
	{\
		return GDK_NEW className();/*return ((className*)(0))->className::rtCreateInstance();*/\
	}\
	gdk::Unknown::Handle_T<gdk::Unknown> className::rtCreateInstance(void) const\
	{\
		return GDK_NEW className();\
	}\
	const gdk::String className::g_className_(__TEXT__(#className));\
	const gdk::ClassId className::g_classId_(makeClassId(className::getClassName_()));\
	const bool className::g_setUpCreator_ = (\
			gdk::Unknown::RtFactory::setupCreator<className>()\
				? (::atexit(gdk::Unknown::RtFactory::unsetupCreator<className>), true)\
				: false\
		);


#define REGISTER_RT_CREATOR(className) \
	static bool const g_##className##_setUpCreator_ = (gdk::nothing(&g_##className##_setUpCreator_), className::g_setUpCreator_);\
	/*DECLARE_FUTILITY_VARIABLE(static bool const,className::g_setUpCreator_);*/




class Stream;
class InputStream;
class OutputStream;

typedef uint32_t ClassId;


__INLINE__ ClassId makeClassId(const String& className)
{
#if defined(_UNICODE)
	StringUtf8 strUtf8 = StringHelper::wideToUtf8(className);
#else
	StringUtf8 strUtf8 = className;
#endif
	return hashValue32(strUtf8, strUtf8.getBufferLength());
}


class GDK_CORE_EXPORT Unknown
{
public:
	template<class TyClass> class Handle_T;

	/*
	 *
	 */
	class GDK_CORE_EXPORT ClassType
	{
		String		_className;
		ClassId	 	_classId;

	public:
		__INLINE__ ClassType(void)
			: _classId(0)
		{}
		ClassType(String const &className);
		void setClass(const Unknown *obj);
		__INLINE__ ClassType(const Unknown *obj) { setClass(obj); }
		Handle_T<Unknown> createInstance(void) const;
		__INLINE__ String const& getClassName(void) const { return _className; }
		__INLINE__ ClassId getClassId(void) const { return _classId; }
	};

	/*
	 *
	 */
	template<class TyClass>
	class Handle_T
	{
	public:
		template<class Tyclass> friend class Handle_T;
		typedef TyClass Ty;

	private:
		TyClass*  _obj;

	public:
		__INLINE__ ~Handle_T(void)
		{
			Unknown const * const obj = _obj;
			if (obj)
			{
				obj->Unknown::release();
			}
		}

		__INLINE__ Handle_T(void)
			: _obj(NULL)
		{
		}

		__INLINE__ Handle_T(TyClass *obj)
		{
			if ((_obj = obj) != NULL)
			{
				((Unknown*)obj)->Unknown::addRef();
			}
		}

		__INLINE__ Handle_T(Handle_T const &p)
		{
			if ((_obj = p._obj) != NULL)
			{
				((Unknown*)_obj)->Unknown::addRef();
			}
		}
		template<typename Tyclass>
		__INLINE__ Handle_T(Handle_T<Tyclass> const &p)
		{
			if ((_obj = p._obj) != NULL)
			{
				((Unknown*)_obj)->Unknown::addRef();
			}
		}

		template< class Tyclass>
		__INLINE__ Tyclass* staticCast(void) const
		{
			return static_cast<Tyclass*>(_obj);
		}
		template< class Tyclass>
		__INLINE__ Tyclass* dynamicCast(void) const
		{
			return dynamic_cast<Tyclass*>(_obj);
		}

		__INLINE__ Handle_T& operator =(TyClass *obj)
		{
			if (obj != NULL)
			{
				((Unknown*)obj)->Unknown::addRef();
			}

			TyClass * const tmp = _obj;
			_obj = obj;

			if (tmp != NULL)
			{
				((Unknown*)tmp)->Unknown::release();
			}

			return *this;
		}
		template<typename Tyclass>
		__INLINE__ Handle_T& operator =(Tyclass *obj)
		{
			TyClass * const o = obj;

			return this->operator =(o);
		}

		__INLINE__ Handle_T& operator =(Handle_T const &p)
		{
			return this->operator =(p._obj);
		}
		template<typename Tyclass>
		__INLINE__ Handle_T& operator =(Handle_T<Tyclass> const &p)
		{
			TyClass * const obj = p._obj;

			return this->operator =(obj);
		}

		__INLINE__ operator TyClass*() const { return _obj; }
		__INLINE__ operator TyClass&() const { return *_obj; }
		__INLINE__ TyClass& operator*() const { return *_obj; }
		__INLINE__ TyClass* operator->() const { return _obj; }

		__INLINE__ bool operator ==(Handle_T const &p) const { return _obj == p._obj; }
		__INLINE__ bool operator !=(Handle_T const &p) const { return _obj != p._obj; }
		__INLINE__ bool operator >=(Handle_T const &p) const { return _obj >= p._obj; }
		__INLINE__ bool operator <=(Handle_T const &p) const { return _obj <= p._obj; }
		__INLINE__ bool operator > (Handle_T const &p) const { return _obj > p._obj; }
		__INLINE__ bool operator < (Handle_T const &p) const { return _obj < p._obj; }
		__INLINE__ bool operator ==(TyClass const *obj) const { return _obj == obj; }
		__INLINE__ bool operator !=(TyClass const *obj) const { return _obj != obj; }
		__INLINE__ bool operator >=(TyClass const *obj) const { return _obj >= obj; }
		__INLINE__ bool operator <=(TyClass const *obj) const { return _obj <= obj; }
		__INLINE__ bool operator > (TyClass const *obj) const { return _obj > obj; }
		__INLINE__ bool operator < (TyClass const *obj) const { return _obj < obj; }

		__INLINE__ bool isNull(void) const { return _obj == NULL; }
		__INLINE__ void setNull(void) { *this = NULL; }
		__INLINE__ TyClass* ptr(void) const { return _obj; }

		__INLINE__ ClassId getClassId(void) const
		{
			return _obj != NULL ? _obj->getClassId() : 0;
		}
		String getClassName(void) const
		{
			return _obj != NULL ? _obj->getClassName() : __TEXT__("");
		}
		ClassType getClassType(void) const
		{
			return _obj != NULL ? _obj->getClassType() : ClassType();
		}
		Handle_T clone(void) const
		{
			return _obj != NULL ? _obj->clone().template dynamicCast<TyClass>() : NULL;
		}

	public:
		template<typename Tyclass> friend __INLINE__ bool operator ==(Handle_T<Tyclass> const &p1, Handle_T const &p2)
		{
			return p2._obj == p1._obj;
		}
		template<typename Tyclass> friend __INLINE__ bool operator !=(Handle_T<Tyclass> const &p1, Handle_T const &p2)
		{
			return p2._obj != p1._obj;
		}
		template<typename Tyclass> friend __INLINE__ bool operator >=(Handle_T<Tyclass> const &p1, Handle_T const &p2)
		{
			return p2._obj < p1._obj;
		}
		template<typename Tyclass> friend __INLINE__ bool operator <=(Handle_T<Tyclass> const &p1, Handle_T const &p2)
		{
			return p2._obj > p1._obj;
		}
		template<typename Tyclass> friend __INLINE__ bool operator > (Handle_T<Tyclass> const &p1, Handle_T const &p2)
		{
			return p2._obj <= p1._obj;
		}
		template<typename Tyclass> friend __INLINE__ bool operator < (Handle_T<Tyclass> const &p1, Handle_T const &p2)
		{
			return p2._obj >= p1._obj;
		}
		template<typename Tyis, typename Tyclass> friend Tyis& operator >>(Tyis &is, Handle_T<Tyclass> &p) __THROW1;
		template<typename Tyos, typename Tyclass> friend Tyos& operator <<(Tyos &os, Handle_T<Tyclass> const &p) __THROW1;
	};

	/* (Run-time Factory)
	 *
	 */
	class RtFactory
	{
	public:
		/* 依据类名创建实例
		*
		*/
		GDK_CORE_EXPORT static Handle_T<Unknown> createClassInstance(const String& className);
		GDK_CORE_EXPORT static Handle_T<Unknown> createClassInstance(ClassId classId);

		/* 安装实例创建者
		*
		*/
		GDK_CORE_EXPORT static bool setupCreator(Handle_T<Unknown>(*creator)(void));
		GDK_CORE_EXPORT static void unsetupCreator(const String& className);

		/* 返回所有类名(Run-time class)
		*
		*/
		GDK_CORE_EXPORT static void getRtClassNames(std::vector<String> &classNames);

		/* 安装实例创建者
		*
		*/
		template<class Tyclass>
		static bool setupCreator(void)
		{
			return setupCreator(&Tyclass::rtCreateInstance_);
		}

		template<class Tyclass>
		static void unsetupCreator(void)
		{
			unsetupCreator(((Tyclass*)(0))->Tyclass::getClassName());
		}
	};



private:
	DECLARE_CLASS_HANDLE(Unknown)
	DECLARE_RT_CREATOR(Unknown)


protected:

#ifdef _WIN32


#pragma push_macro("new")
#undef new

	__INLINE__ void* __CDECL__ operator new(size_t nSize, int, const char *pFilename, int nLine, const char *pFunction)
	{
		return ::operator new(nSize, 0, pFilename, nLine, pFunction);
	}
	__INLINE__ void  __CDECL__ operator delete(void *p, int, const char *pFilename, int nLine, const char *pFunction)
	{
		return ::operator delete(p, 0, pFilename, nLine, pFunction);
	}

	__INLINE__ void* __CDECL__ operator new(size_t nSize)
	{
		return ::operator new(nSize, 0, __FILE__, __LINE__, __FUNCSIG__);
	}
	__INLINE__ void  __CDECL__ operator delete(void *p)
	{
		return ::operator delete(p, 0, __FILE__, __LINE__, __FUNCSIG__);
	}

	__INLINE__ void* __CDECL__ operator new(size_t nSize, void *_Where, int, const char *pFilename, int nLine, const char *pFunction)
	{
		return ::operator new(nSize, _Where, 0, pFilename, nLine, pFunction);
	}
	__INLINE__ void  __CDECL__ operator delete(void *p, void *_Where, int, const char *pFilename, int nLine, const char *pFunction)
	{
		return ::operator delete(p, _Where, 0, pFilename, nLine, pFunction);
	}

	__INLINE__ void* __CDECL__ operator new(size_t nSize, void *_Where)
	{
		return ::operator new(nSize, _Where, 0, __FILE__, __LINE__, __FUNCSIG__);
	}
	__INLINE__ void  __CDECL__ operator delete(void *p, void *_Where)
	{
		return ::operator delete(p, _Where, 0, __FILE__, __LINE__, __FUNCSIG__);
	}

	__INLINE__ void* __CDECL__ operator new(size_t nSize, int, const char *pFilename, int nLine)
	{
		return ::operator new(nSize, 0, pFilename, nLine, NULL);
	}
	__INLINE__ void  __CDECL__ operator delete(void *p, int, const char *pFilename, int nLine)
	{
		return ::operator delete(p, 0, pFilename, nLine, NULL);
	}

	__INLINE__ void* __CDECL__ operator new(size_t nSize, const char *pFilename, int nLine)
	{
		return ::operator new(nSize, 0, pFilename, nLine, NULL);
	}
	__INLINE__ void  __CDECL__ operator delete(void *p, const char *pFilename, int nLine)
	{
		return ::operator delete(p, 0, pFilename, nLine, NULL);
	}

	__INLINE__ void* __CDECL__ operator new(size_t nSize, void *_Where, int, const char *pFilename, int nLine)
	{
		return ::operator new(nSize, _Where, 0, pFilename, nLine, NULL);
	}
	__INLINE__ void  __CDECL__ operator delete(void *p, void *_Where, int, const char *pFilename, int nLine)
	{
		return ::operator delete(p, _Where, 0, pFilename, nLine, NULL);
	}

	__INLINE__ void* __CDECL__ operator new(size_t nSize, void *_Where, const char *pFilename, int nLine)
	{
		return ::operator new(nSize, _Where, 0, pFilename, nLine, NULL);
	}
	__INLINE__ void  __CDECL__ operator delete(void *p, void *_Where, const char *pFilename, int nLine)
	{
		return ::operator delete(p, _Where, 0, pFilename, nLine, NULL);
	}

//protected:
//	__INLINE__ void* __CDECL__ operator new[](size_t nSize,int,const char *pFilename,int nLine,const char *pFunction)
//	{
//		GDK_ASSERT(false);
//
//		return ::operator new[](nSize,0,pFilename,nLine,pFunction);
//	}
//	__INLINE__ void __CDECL__ operator delete[](void *p,int,const char *pFilename,int nLine,const char *pFunction)
//	{
//		GDK_ASSERT(false);
//	}
//
//	__INLINE__ void* __CDECL__ operator new[](size_t nSize)
//	{
//		GDK_ASSERT(false);
//
//		return ::operator new[](nSize);
//	}
//	__INLINE__ void __CDECL__ operator delete[](void *p)
//	{
//		GDK_ASSERT(false);
//	}
//
//	__INLINE__ void* __CDECL__ operator new[](size_t nSize,void *_Where,int,const char *pFilename,int nLine,const char *pFunction)
//	{
//		GDK_ASSERT(false);
//
//		return ::operator new[](nSize,_Where,0,pFilename,nLine,pFunction);
//	}
//	__INLINE__ void __CDECL__ operator delete[](void *p,void *_Where,int,const char *pFilename,int nLine,const char *pFunction)
//	{
//		GDK_ASSERT(false);
//	}
//
//	__INLINE__ void* __CDECL__ operator new[](size_t nSize,void *_Where)
//	{
//		GDK_ASSERT(false);
//
//		return ::operator new[](nSize,_Where);
//	}
//	__INLINE__ void __CDECL__ operator delete[](void *p,void *_Where)
//	{
//		GDK_ASSERT(false);
//	}

#pragma pop_macro("new")

#endif


private:
	uint32_t mutable volatile  _refs;

public:
	__INLINE__ Unknown& operator =(const Unknown &) { return *this; }

protected:
	__INLINE__ Unknown(void)
		: _refs(0)
	{}

	__INLINE__ virtual ~Unknown(void)
	{}

private:
	__INLINE__ void addRef(void) const { atomic_increment(&_refs); }
	void release(void) const;

public:
	__INLINE__ uint32_t getReferenceCount(void) const { return _refs; }
	ClassType getClassType(void) const;

public:
	Handle clone(void) const;
	__INLINE__ virtual void importFrom(InputStream &is) __THROW1 { (void)&is; }
	__INLINE__ virtual void exportTo(OutputStream &os) const __THROW1 { (void)&os; }

public:
	template<typename Tyis> friend Tyis& operator >>(Tyis &is, Unknown &r) __THROW1;
	template<typename Tyos> friend Tyos& operator <<(Tyos &os, Unknown const &r) __THROW1;

};


typedef Unknown::ClassType ClassType;
typedef Unknown::RtFactory RtFactory;


template<typename TyIs>
__INLINE__ TyIs& operator >>(TyIs &is, Unknown &r) __THROW1
{
	(void)&r;

	return is;
}
template<typename TyOs>
__INLINE__ TyOs& operator <<(TyOs &os, Unknown const &r) __THROW1
{
	(void)&r;

	return os;
}

template<typename TyIs, typename TyClass>
TyIs& operator >>(TyIs &is, Unknown::Handle_T<TyClass> &obj) __THROW1
{
	char flag;
	is >> flag;

	switch (flag)
	{
	case 'O':
		{
			/*
			String className;
			io >> className;

			*this = RtFactory::createClassInstance(className).dynamicCast<TyClass>();
			*/
			ClassId classId;
			is >> classId;

			obj = RtFactory::createClassInstance(classId).dynamicCast<TyClass>();
			if (obj == NULL) {
				String errMsg;
				errMsg.format(__TEXT__("TyIs& operator >>(TyIs &, " STRING_FMT "::Handle &)"), (Char const*)typeid_className<TyClass>());
				__THROW__((Char const*)errMsg);
			}

			obj->importFrom(is);
		}
		break;

	case 'o':
		{
			obj = NULL;
		}
		break;

	default:
		{
			String errMsg;
			errMsg.format(__TEXT__("TyIs& operator >>(TyIs &, " STRING_FMT "::Handle &) Error!"), (Char const*)typeid_className<TyClass>());
			__THROW__((Char const*)errMsg);
		}
		break;
	}

	return is;
}
template<typename TyOs, typename TyClass>
TyOs& operator <<(TyOs &os, Unknown::Handle_T<TyClass> const &obj) __THROW1
{
	if (obj != NULL)
	{
		char flag('O');

		/*
		os	<< flag
			<< obj->getClassName();
		*/
		os << flag
		   << obj->getClassId();

		obj->exportTo(os);
	}
	else
	{
		char c('o');

		os << c;
	}
	return os;
}



///////////////////////////////////////////////////////
template<class TyClass>
class Class_T : public TyClass, virtual public Unknown
{
public:
	DECLARE_CLASS_HANDLE(Class_T)
	DECLARE_CLASS_INSTANCE(Class_T)

protected:
	Class_T(void)
	{}
};










}//namespace gdk



#endif /*__GDK_UNKNOWN_H__*/
